<?php
/**
 * 
 * Класс для работы с макетом
 * @author andrew
 *
 */
class Nimblecms_Layout {
	
	/**
	 * Конец строки
	 * @var string
	 */
	const EOL = "\n";
	
	/**
	 * 
	 * Layout файл
	 * @var string
	 */
	protected $_layout = null;
	
	/**
	 * 
	 * Объект 
	 * @var Nimblecms_Layout
	 */
	private static  $_object = null;
	
	public static function getInstance() {
		if(self::$_object === null) {
			self::$_object = new Nimblecms_Layout();
		}
		return self::$_object;
	}
	
	/**
	 * 
	 * Сохраняет макет
	 * @param array $layout
	 */
	public function save(array $layout) {
		$output = '<?xml version="1.0" encoding="UTF-8"?>' . self::EOL;
		$output .= '<layout>' . self::EOL;
		$output .= self::_saveContainer($layout);
		$output .= '</layout>';
		
		$f = fopen($this->_layout,'w');
		fwrite($f, $output);
		fclose($f);
		
		return $output;
	}
	
	/**
	 * 
	 * Сохраняем контейнер
	 * @param array $container
	 */
	private static function _saveContainer(array $container) {
		$isRoot = ($container['isRoot'] == 1);
		
		$depth = ($container['isRoot'] == 1) ? 0 : $container['depth'];
		
		$output = '';
		
		$pos = isset($container['position']) ? $container['position'] : '';
		
		$pos2 = isset($container['position']) ? ' position="' . $container['position'] . '"' : '';
		if (!$isRoot) {
			$output .= str_repeat('    ', $depth) . '<container cols="' . $container['cols'] . '"' . $pos2 . '>' . self::EOL;
		}
		
		foreach ($container['containers'] as $index => $childContainer) {
			$childContainer['depth'] = $depth + 1;
			$output .= self::_saveContainer($childContainer);
		}
		
		foreach ($container['widgets'] as $index => $widget) {
			$widget['container'] = $container;
			$output .= self::_saveWidget($widget);
		}
		if (!$isRoot) {
			$output .= str_repeat('    ', $depth) . '</container>' . self::EOL;
		}
		
		
		return $output;
	}
	
	/**
	 * 
	 * Сохраняем виджет
	 * @param array $widget
	 */
	private static function _saveWidget(array $widget) {
		$depth   = $widget['container']['depth'];
		$indent = str_repeat('    ', $depth + 1);
		
		$load = 'php';
		
		$output = $indent . '<widget module="' . $widget['module'] . '" name="' . $widget['name'] . '" load="' . $load . '">' . self::EOL;
		
		if ($widget['title']) {
			$output .= $indent . '    <title><![CDATA[' . $widget['title'] . ']]></title>' . self::EOL;	
		}
		
		if (count($widget['resources']['css']) > 0 || count($widget['resources']['javascript']) > 0) {
			$output .= $indent . '    <resources>' . self::EOL;
			foreach ($widget['resources']['css'] as $index => $css) {
				$output .= $indent . '        <resource type="css" src="' . $css . '" />' . self::EOL;
			}
			foreach ($widget['resources']['javascript'] as $index => $js) {
				if (is_array($js)) {
					if (!array_key_exists('file', $js)) {
						continue;	
					}
					$js = $js['file'];
				}
				$output .= $indent . '        <resource type="javascript" src="' . $js . '" />' . self::EOL;
			}
			$output .= $indent . '    </resources>' . self::EOL;
		}
		
		if (count($widget['params']) > 0) {
			$output .= $indent . '    <params>' . self::EOL;
			foreach ($widget['params'] as $param => $data) {
				if ($data['type'] == 'global') {
					$output .= $indent . '        <param name="' . $param . '" type="global" />' . self::EOL;
				} else {
					/**
					 * Use CDATA to store the value of param
					 */
					$value   = ltrim($data['value'], ' ');
					$value   = rtrim($value, ' ');
					$output .= $indent . '        <param name="' . $param . '"><value><![CDATA[' . $value . ']]></value></param>' . self::EOL;
				}
			}
			$output .= $indent . '    </params>' . self::EOL;
		}
		
		$output .= $indent . '</widget>' . self::EOL;
		return $output;
	}
	
	/**
	 * Устанавливает layout
	 * @param string $layout
	 * @throws Zend_Exception
	 */
	public function setLayout($layout) {
		$path = APPLICATION_PATH . DS . "layouts" . DS . "scripts" . DS . $layout;
		
		if(!file_exists($path))
			throw new Zend_Exception('Layout not found in ' . APPLICATION_PATH . DS . "layouts" . DS . "scripts" . DS);
		
		if($this->_layout === null)	$this->_layout = $path;
		
		return $this;
	}
	
	/**
	 * Возвращает путь к layout если он установлен
	 */
	public function getLayout() {
		if($this->_layout !== null) return $this->_layout; else return null;
	}
	/**
	 * 
	 * Загружает структуру макета страницы
	 */
	public function load() {
		$xml = simplexml_load_file($this->_layout);
		
		$array = self::_loadContainer($xml);
		
		$return = array(
			'isRoot' => 1,
			'cols' => 12,
			'containers' => $array['containers'],
			'widgets' => $array['widgets']
		);
		return $return;
	}
	
	/**
	 * Загружает контейнер
	 * @param object $xmlContainerNode
	 */
	private static function _loadContainer($xmlContainerNode) {
		$return = array(
			'containers' => null,
			'widgets' => null
		);
		
		if($xmlContainerNode === null) 
			return $return;
			
		$attributes = $xmlContainerNode->attributes();
		
		$return = array(
			'isRoot' => 0,
			'cols' => (string)$attributes['cols'],
			'containers' => array(),
			'widgets' => array()
		);
		
		$pos = (string)$attributes['position'];
		
		if($pos) {
			$return['position'] = $pos;
		}
		
		foreach ($xmlContainerNode->container as $node) {
			$return['containers'][] = self::_loadContainer($node);
		}
		if($xmlContainerNode->defaultOutput) {
			$return['widgets'][] = array(
				'module' => null,
				'name' => null,
				'title' => null,
				'resources' => null,
				'params' => null
			);
		}
		foreach ($xmlContainerNode->widget as $node) {
			$return['widgets'][] = self::_loadWidget($node);
		}
		return $return;
	}
	/**
	 * 
	 * Загружает виджеты из контейнера
	 * @param object $xmlWidgetNode
	 */
	private static function _loadWidgets($xmlWidgetNode) {
		if(null === $xmlWidgetNode)
			return array();
			
		$attributes = $xmlWidgetNode->attributes();
		$title 	= isset($xmlWidgetNode->title) ? (string)$xmlWidgetNode->title : '';
		
		$return = array(
			'module' 	=> (string) $attributes['module'],
			'name' 		=> (string) $attributes['name'],
			'title' 	=> $title,
			'load'		=> (string) $attributes['php'],
			'resources' => array(),
			'params' 	=> array(),
		);
		
		if ($xmlWidgetNode->resources) {
			foreach ($xmlWidgetNode->resources->resource as $resource) {
				$attrs = $resource->attributes();
				$type  = (string) $attrs['type'];
				$src   = (string) $attrs['src'];
				if (!isset($return['resources'][$type])) {
					$return['resources'][$type] = array();
				}
				$return['resources'][$type][] = $src;
			}
		}
		if ($xmlWidgetNode->params) {
			foreach ($xmlWidgetNode->params->param as $param) {
				$attrs = $param->attributes();
				$name  = (string) $attrs['name'];
				$return['params'][$name] = array(
					'value' => (string) $param->value,
					'type'  => isset($attrs['type']) ? 'global' : '',
				);
			}
		}
		return $return;
	}
	
	
}